package com.addzero.kmp.processor

import cn.hutool.core.io.FileUtil
import cn.hutool.core.io.FileUtil.file
import com.addzero.kmp.context.SettingContext
import com.google.devtools.ksp.symbol.ClassKind
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSDeclaration
import com.google.devtools.ksp.symbol.KSType
import java.io.File

// 定义Kotlin标准库类型，这些类型通常不需要导入
private val kotlinStdTypes = setOf(
    "String", "Int", "Long", "Double", "Float", "Boolean", "Short", "Byte", "Char",
    "List", "Set", "Map", "MutableList", "MutableSet", "MutableMap"
)

// 判断是否为Jimmer实体接口
private fun isJimmerEntity(typeDecl: KSDeclaration): Boolean {
    return typeDecl.annotations.any { it.shortName.asString() == "Entity" } &&
            (typeDecl as? KSClassDeclaration)?.classKind == ClassKind.INTERFACE
}

// 判断是否为枚举类
private fun isEnum(typeDecl: KSDeclaration): Boolean {
    return (typeDecl as? KSClassDeclaration)?.classKind == ClassKind.ENUM_CLASS
}

// 获取类型在同构体中的字符串表示
// 它不再收集导入，只返回类型字符串
private fun getIsoTypeString(
    type: KSType,
    outputDir: String,
    generatedIsoClasses: MutableSet<String>, // 跟踪所有已生成同构体的FQCN
    packageName: String // 生成的同构体文件所在的包名
): String {
    val typeDecl = type.declaration
    val typeName = typeDecl.simpleName.asString()
    val isNullable = type.isMarkedNullable
    val isJimmer = isJimmerEntity(typeDecl)
    val typeArgs = type.arguments

    // 递归处理泛型参数
    val typeArgsStr = if (typeArgs.isNotEmpty()) {
        typeArgs.joinToString(", ") { arg ->
            arg.type?.resolve()?.let {
                getIsoTypeString(it, outputDir, generatedIsoClasses, packageName)
            } ?: "Any"
        }
    } else ""

    return when {
        // 处理集合类型，泛型参数会被递归处理并附带Iso后缀
        (typeName == "List" || typeName == "Set" || typeName == "Map") && typeArgs.isNotEmpty() -> {
            "${typeName}<${typeArgsStr}>${if (isNullable) "?" else ""}"
        }
        // 处理Jimmer实体类型，递归生成同构体并返回带Iso后缀的类型名
        isJimmer -> {
            generateIsomorphicDataClass(typeDecl as KSClassDeclaration, outputDir, generatedIsoClasses, packageName, isomorphicClassSuffix = SettingContext.settings.isomorphicClassSuffix)
            "${typeName}Iso${if (isNullable) "?" else ""}"
        }
        // 其他类型（包括枚举和普通类），直接返回其简单名称
        else -> {
            "${typeName}${if (isNullable) "?" else ""}"
        }
    }
}

// 生成同构体数据类的主函数
fun generateIsomorphicDataClass(
    ksClass: KSClassDeclaration,
    outputDir: String = "shared/src/commonMain/kotlin/com/addzero/kmp/isomorphic",
    generatedIsoClasses: MutableSet<String> = mutableSetOf<String>(), // 跟踪所有已生成同构体的FQCN
    packageName: String = "com.addzero.kmp.isomorphic",
    isomorphicClassSuffix: String="Iso", // 生成的同构体文件所在的包名
) {
// val   jimmerEntityPkg: String="com.example.model"
    val jimmerEntityPkg = ksClass.packageName.asString()
    println("Jimmer实体包：$jimmerEntityPkg")
    val className = ksClass.simpleName.asString()
    val dataClassName = "${className}$isomorphicClassSuffix"
    val currentIsoFqName = "$packageName.$dataClassName"

    // 如果该同构体已被生成，则直接返回，避免重复
    if (currentIsoFqName in generatedIsoClasses) {
        return
    }
    generatedIsoClasses += currentIsoFqName

    // 收集当前同构体文件需要的所有导入
    val localImports = mutableSetOf<String>()

    val props = ksClass.getAllProperties().map { prop ->
        val name = prop.simpleName.asString()
        val type = prop.type.resolve() // 属性的KSType
        val typeDecl = type.declaration // 属性类型的声明
        val typeName = typeDecl.simpleName.asString() // 属性类型的简单名称
        val qualifiedName = typeDecl.qualifiedName?.asString() // 属性类型的全限定名

        // 获取属性在同构体中的字符串表示（可能带Iso后缀）
        val typeStr = getIsoTypeString(type, outputDir, generatedIsoClasses, packageName)

        // 判断是否需要导入
        when {
            // 如果是Jimmer实体，其Iso同构体在同一包下，无需导入。
            // 递归生成已在getIsoTypeString中处理。
            isJimmerEntity(typeDecl) -> { /* 无需额外导入 */
            }
            // 如果是枚举或其他自定义类型，且不是Kotlin标准库类型
            !kotlinStdTypes.contains(typeName) && qualifiedName != null -> {
                val importPackage = qualifiedName.substringBeforeLast('.', "")
                // 确保导入的不是当前生成的包，也不是原始的Jimmer实体包
                // TODO: 这里的Jimmer实体包路径需要根据你的实际情况精确配置
                // 示例：如果你的Jimmer实体在 com.addzero.web.modules.xxx.entity 包下
                if (importPackage != packageName && !qualifiedName.startsWith(jimmerEntityPkg)) {
                    localImports.add(qualifiedName)
                }
            }
            // 处理集合和Map的泛型参数导入
            (typeName == "List" || typeName == "Set") && type.arguments.isNotEmpty() -> {
                type.arguments.first().type?.resolve()?.let { argType -> // ✅ 获取 KSType
                    val argTypeDecl = argType.declaration
                    val argSimpleName = argTypeDecl.simpleName.asString()
                    val argQualifiedName = argTypeDecl.qualifiedName?.asString()
                    val argPackage = argQualifiedName?.substringBeforeLast('.', "")

                    if (argQualifiedName != null && !kotlinStdTypes.contains(argSimpleName) && argPackage != packageName && !isJimmerEntity(argTypeDecl)) {
                        localImports.add(argQualifiedName)
                    }
                }
            }

            typeName == "Map" && type.arguments.size == 2 -> {
                // 处理Map的Key类型导入
                type.arguments[0].type?.resolve()?.let { keyType -> // ✅ 获取 KSType
                    val keyTypeDecl = keyType.declaration
                    val keySimpleName = keyTypeDecl.simpleName.asString()
                    val keyQualifiedName = keyTypeDecl.qualifiedName?.asString()
                    val keyPackage = keyQualifiedName?.substringBeforeLast('.', "")
                    if (keyQualifiedName != null && !kotlinStdTypes.contains(keySimpleName) && keyPackage != packageName) {
                        localImports.add(keyQualifiedName)
                    }
                }
                // 处理Map的Value类型导入
                type.arguments[1].type?.resolve()?.let { valueType -> // ✅ 获取 KSType
                    val valueTypeDecl = valueType.declaration
                    val valueSimpleName = valueTypeDecl.simpleName.asString()
                    val valueQualifiedName = valueTypeDecl.qualifiedName?.asString()
                    val valuePackage = valueQualifiedName?.substringBeforeLast('.', "")
                    if (valueQualifiedName != null && !kotlinStdTypes.contains(valueSimpleName) && valuePackage != packageName && !isJimmerEntity(valueTypeDecl)) {
                        localImports.add(valueQualifiedName)
                    }
                }
            }
        }
        "val $name: $typeStr"
    }.joinToString(",\n    ")

    // 生成最终的导入字符串，过滤、去重、排序
    val finalImportStr = localImports
        .filter { importFqName ->
            // 排除当前包下的类型
            !importFqName.startsWith(packageName)
        }
        .distinct()
        .sorted()
        .joinToString("\n") { "import $it" }

    val code = """
        |package $packageName
        |
        |$finalImportStr
        |
        |data class $dataClassName(
        |    $props
        |)
    """.trimMargin()

//    val file = File("$outputDir/${dataClassName}.kt")
    val file = FileUtil.file("$outputDir/${dataClassName}.kt")

    if (SettingContext.settings.skipExistsFiles.toBoolean()) {
        if (file.exists()) {
            return
        }

    }

    file.parentFile?.mkdirs()
    FileUtil.writeUtf8String(code, file)
    println("生成同构体：$dataClassName 到 ${file.absolutePath}")

//    file.writeText(code)
}